//============================================================================
//
// saGroupManager.js
// -----------------
//
// This file is part of the API for the s-audit internals. This module
// performs group management utiltites, accessed by the "group" subcommand
// from the CLI. Each function returns a simple object, which is presented
// by a callback in the client layer for presentation.
//
//============================================================================

// We need a database connection and a config file.

var sqlite3 = require('sqlite3').verbose(); 
var config = require('jsonconfig');

config.load(['config/config.json']);

// Get a database connection and make sure foreign keys are enforced. The
// path to the database file is in the config file.

var db = new sqlite3.Database(config.DB, function() {
	db.run('PRAGMA foreign_keys=on');
	}
);

// A couple of simple validation functions. We only want to accept
// alphanumerics, dash and underscore. Group names can be a maximum of 32
// characters, group comments a maximum of 1k.

var validateGroup = function(group) {

    if (group.length < 1 || group.length > 32) {
        throw('Group names must be 1-32 characters.');
    }

    if (group.match(/[^A-Za-z0-9\-_]/)) {
        throw('Group name contains invalid character(s).');
    }

    return group;
}

var validateComment = function(comment) {

    if (comment.length < 1 || comment.length > 1024) {
        throw('Comments must be 1-1024 characters.');
    }

    if (comment.match(/[^A-Za-z\-_ , \.']/)) {
        throw('Comment contains invalid character(s).');
    }

    return comment;
}

//----------------------------------------------------------------------------
// EXPORTED METHODS

module.exports = {

	groupList: function(callback) {

		// Print a list of all known groups, with their comment strings

		db.all('SELECT * from audit_groups', callback);
	},

	groupCreate: function(args, callback) {
		
		// Create a new group. Uses DB constraints to make sure duplicates
		// can't be created

		// args[0] is the group name
		// args[1] is an optional comment

		args[0] = validateGroup(args[0]);
	
		db.run('INSERT INTO audit_groups VALUES(null, ?, ?)', args,
		callback);
	},

	groupDelete: function(group, callback) {
	
		// Delete a group. DB constraints stop us removing non-existent
		// groups. Foriegn keys cascade down, removing all hosts in the
		// group, all zones from those hosts, and all data for those zones,
		// so CALL WITH CARE!

		// group is the name of the group to remove

		db.run('DELETE FROM audit_groups WHERE name = ?',
		validateGroup(group), callback);
	},

	groupComment: function(group, comment, callback) {

		// Set the comment string for a group
	
		db.run('UPDATE audit_groups SET comment = ? WHERE name = ?',
		validateComment(comment), validateGroup(group), callback);
	},

	groupRename: function(group, new_name, callback) {
	
		// Rename a group.
	
		db.run('UPDATE audit_groups SET name = ? WHERE name = ?',
		validateGroup(group), validateGroup(new_name), callback);
	},

	groupShow: function(group, callback) {

		// Return an object containing the hostnames of all hosts in the
		// given group
		
		db.all('SELECT hosts.hostname FROM hosts INNER JOIN audit_groups \
		ON audit_groups.id = hosts.audit_group  \
		WHERE audit_groups.name = ? ORDER BY hosts.hostname ASC',
		validateGroup(group), callback);
	},

	groupCount: function(group, callback) {
		
		// Return the number of hosts in the given group as res.host_count.
		// Returns undefined if the group does not exist

		db.get('SELECT id FROM audit_groups WHERE name = ?',
		validateGroup(group), function(err, res) {

			if (err) {
				throw(err);
			}

			if (res === undefined) {
				callback(null, undefined);
			}
			else {
				db.get('SELECT COUNT(1) AS host_count FROM hosts WHERE \
				audit_group = ?', res.id, callback);
			}

		});
	},

	groupExport: function(group, callback) {

		// Export all hosts in a group into a JSON file.

		console.log('Group export is not implemented.');
	},

	groupImport: function(group, filename, callback) {

		// Import a group from a JSON file

		console.log('Group import is not implemented.');
	}

}
